#ifndef __RASTERSCANTWOPASS_H__
#define __RASTERSCANTWOPASS_H__

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include "../linkedList/linkedListAPI.h"
#ifndef __COMPLEX_H__
#define __COMPLEX_H__
#include <complex.h>
#endif

/* ------------------------ Type Definitions ------------------------ */

typedef struct RASTERSCANTWOPASS_PNMIMAGE 
{
  unsigned char **rawImage;
  int nrows, ncols;
  char name[72];
} RASTERSCANTWOPASS_IMG, *RASTERSCANTWOPASS_IMGPTR;

/* TODO: move this to the API */
typedef enum eRasterScanTwoPassDisplayType
{
  RASTERSCANTWOPASS_NO_DISPLAY,
  RASTERSCANTWOPASS_DISPLAY_END,
  RASTERSCANTWOPASS_DISPLAY_RASTERSCANTWOPASS_ANIMATION
} RASTERSCANTWOPASSDISPLAYTYPE;

typedef struct LIST_DATA_STRUCTURE
{
  unsigned int xCoordLink1;
  unsigned int yCoordLink1;
  unsigned char labelLink1;

  unsigned int xCoordLink2;
  unsigned int yCoordLink2;
  unsigned char labelLink2;
} listData;

typedef struct LIST_FINAL_LABEL
{
  unsigned char firstPassLabel;
  unsigned char finalLabel;
} listFinalLabel;

  


/* ------------------------ Private Attributes ------------------------ */
unsigned int loopCountX;               // counter for the x direction
unsigned int loopCountY;               // counter for the y direction
unsigned int totalRasterScanTwoPassRecursiveCall;   // keeps track of total recursive calls
unsigned int maxRecursiveCallStack;    // maintains max stack count for recurs call
unsigned char labelName;             // label counter to control label names
unsigned char finalLabelName;
unsigned int printAnimation;
unsigned char buf[64];                 // buffer for line read from file 
listData listDataBuffer;
List *equivalenceList[100];
List * finalTagList;
unsigned int equivalenceListCounter;
RASTERSCANTWOPASS_IMG rasterScanTwoPassImage;                    // raw image data

/* ------------------------ Function Mappings ------------------------ */

#define p_initRasterScanTwoPass                  i_initRasterScanTwoPass
#define p_printRasterScanTwoPassMatrix           i_printRasterScanTwoPassMatrix
#define p_startAutoRasterScanTwoPass             i_startAutoRasterScanTwoPass
#define p_deallocRasterScanTwoPass               i_deallocRasterScanTwoPass

/* ------------------------ Inlined Methods ------------------------ */

#define p_getTotalRecursiveCalls()  totalRasterScanTwoPassRecursiveCall
#define p_rasterScanTwoPassGetNumberOfPixels()      (rasterScanTwoPassImage.nrows * rasterScanTwoPassImage.ncols)
#define westPixel                   rasterScanTwoPassImage.rawImage[loopCountY][loopCountX - 1]
#define northPixel                  rasterScanTwoPassImage.rawImage[loopCountY - 1][loopCountX]
#define currentPixel                rasterScanTwoPassImage.rawImage[loopCountY][loopCountX]

/* ------------------------ Public Methods ------------------------ */
void i_initRasterScanTwoPass(char * rasterScanTwoPassFileName);
void i_printRasterScanTwoPassMatrix(void);
void i_startAutoRasterScanTwoPass(RASTERSCANTWOPASSDISPLAYTYPE rasterScanTwoPassDisplayType);
void i_deallocRasterScanTwoPass(void);

/* ------------------------ Private Methods ------------------------ */

void rasterScanTwoPassScanOne(void);
void rasterScanTwoPassScanTwo(void);
unsigned char westPixelValue(void);
unsigned char northPixelValue(void);
unsigned char **rasterScanTwoPassAllocateMatrix(int length, int height);
void removeListItemFromMemory(void * data);
unsigned int compareListItemCallBack(void * dataStruct, void * data);
unsigned int compareListEquivalenceExist(void * listStruct, void * newStruct);
void checkForNeedToMergeLists(void);
unsigned int compareListEquivalenceExist(void * listStruct, void * newStruct);
void mergeLists(unsigned int mergePut, unsigned int mergeGet);
unsigned int checkForExistence(unsigned int listToCheck, listData * listDataPtr);
unsigned int compareFinalLabelCallBack(void * listStruct, void * firstPassLabel);
void insertIntoFinalList(char currentLabel, char finalLabel);
void finalLabelRoutine(void);
void printFinalList(void);
void removeFinalTagListItemFromMemory(void * data);



#endif
